#!/usr/bin/env python3
# -*- coding:UTF-8 -*-
#对于操作系统而言，一个任务就是一个进程。但是一个任务有不同的子任务，子任务对应的概念就是线程
#因为每个进程至少要干一件事，因此一个进程至少有一个线程。
#如何执行多任务程序？
#方案一：启动多个进程，多个进程一块执行任务
#方案二：一个进程启动多个线程，每个线程执行不同的任务
#无论是多进程，还是多线程，都是需要相互通信和协调的。而且因为多线程的执行逻辑由很高的相关性，因此难度大于单进程单线程程序。
#进程和线程的调度，完全由操作系统决定，编程时只需要调用接口，向操作系统说明程序运行方式即可。
#操作系统有一个fork()的系统调用，编程语言的多进程实现，均是调用fork()系统调用的结果
#fork()系统调用的不同之处在于，其他系统调用，只返回一次，而fork()调用，返回两次
#因为操作系统会把当前进程复制一份，然后子进程和父进程中返回.子进程返回0，而父进程返回子进程的ID
#父进程需要管理子进程，因此它会记住子进程的ID，而子进程只需要调用getppid()函数,就知道父进程的ID

import os,time,random
from multiprocessing import Process,Pool #从multiprocessing模块中导入Process类
#print("process [%s] start..." % os.getpid())
pid = os.fork() #有两次返回,下面的代码需要在两个进程中分别执行
if pid == 0:
    print("I am a child process [%s] of my father process [%s]" % (os.getpid(),os.getppid()))
else:
    print("I [%s] just created a child process [%s]" % (os.getpid(),pid))
print("分隔符\n")

#python 多进程模块的应用
def run_proc(name):
    print("Run child process %s [%s]" % (name,os.getpid()))

#if __name__ == '__main__':
  #  print("Parent process %s." % os.getpid()) #父进程执行，打印信息
  #  child = Process(target=run_proc,args=('test',)) #定义子进程
  #  print("Child process will start")
  #  child.start() #开始执行
  #  child.join() #等待结束
  #  print("Child process end.")

#Python 进程池
#定义子进程任务函数
print("进程池分割标记")
def long_time_task(name):
    print("Run task %s,pid is [%s]" %(name,os.getpid()))
    starttime = time.time()
    #time.sleep(random.random() * 3)
    time.sleep(10)
    endtime = time.time()
    print("Task %s runs %0.2f seconds." % (name,(endtime - starttime)))

#定义主进程任务调度
if __name__ == '__main__':
    print("parent process %s." % os.getpid())
    child = Pool(4) #启动四个子进程
    for i in range(5):
        child.apply_async(long_time_task,args=(i,))
    print("Waiting for all  subprocesses done.")
    child.close()
    child.join()
    print("All process done.")